package com.kingschan.util.bean;

import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import org.apache.log4j.Logger;
import org.json.JSONObject;
import com.kingschan.jeasytag.tag.RootTag;
import com.kingschan.util.lang.ArrayUtil;


/**
 * <pre>
 * @author kingschan
 * date:2013-3-2
 * description:java bean util
 *</pre>
 */
public class BeanUtil {
	private static Logger log = Logger.getLogger(BeanUtil.class);
	/**
	 * copySameFieldToBean
	 * @param objData
	 * @param target
	 * @return
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 * @throws IntrospectionException 
	 * @throws InvocationTargetException 
	 * @throws IllegalArgumentException 
	 */
	public static Object copySameFieldToBean(Object objData,Class<?> target) throws InstantiationException, IllegalAccessException, IntrospectionException, IllegalArgumentException, InvocationTargetException{
		Object o = target.newInstance();
		Map<String, Object> map =BeanUtil.getAccessFields(objData);
		PropertyDescriptor[] propertys=Introspector.getBeanInfo(o.getClass()).getPropertyDescriptors();
		for (PropertyDescriptor p : propertys) {
			if (map.containsKey(p.getDisplayName())) {				
				p.getWriteMethod().invoke(o, map.get(p.getDisplayName()));
			}
		}
		return o;
	}
	/**
	 * get Access Fields for current class
	 * @param obj
	 * @return
	 * @throws IntrospectionException 
	 * @throws InvocationTargetException 
	 * @throws IllegalAccessException 
	 * @throws IllegalArgumentException 
	 */
	public static Map<String, Object> getAccessFields(Object obj) throws  IllegalArgumentException, IllegalAccessException, InvocationTargetException{
		Map<String, Object> map = new HashMap<String, Object>();
		Field[] fields=obj.getClass().getDeclaredFields();
		Object value=null;
		PropertyDescriptor p;
		for (Field f : fields) {		
			try {
				p = new PropertyDescriptor(f.getName(), obj.getClass());
				value =p.getReadMethod().invoke(obj);
			} catch (IntrospectionException e) {				
				e.printStackTrace();
				continue;
			}			
			if (null!=value) {
				log.debug(String.format(" add filed: %s value: %s", f.getName(),value));
				map.put(f.getName(), value);
			}			
			
		}
		return map;
	}

	/**
	 * Serialization Object to natival file
	 * @param path
	 * @param s
	 * @throws IOException
	 */
	public static void serializationObject(String path,java.io.Serializable s) throws IOException{
		FileOutputStream fos = new FileOutputStream(path);
		ObjectOutputStream oos = new ObjectOutputStream(fos);
		oos.writeObject(s);
		fos.close();
	}
	/**
	 * DesSerializationObject
	 * @param path
	 * @return
	 * @throws IOException
	 * @throws ClassNotFoundException
	 */
	public static Object DesSerializationObject(String path) throws IOException, ClassNotFoundException{
		FileInputStream fis = new FileInputStream(path);
		ObjectInputStream ois = new ObjectInputStream(fis);
		Object obj=ois.readObject();
		fis.close();
		return obj;
	}
	
	/**
	 *GetAllFields  break for RootTag.class.getSimpleName()
	 * <font style="color:red;">contrain super class of fields /font>
	 * @param tag
	 * @return
	 */
	public static Field[] getAllFields(Object tag){
		Field [] f ={};
		if (tag.getClass().getSimpleName().equals(RootTag.class.getSimpleName())) {
			f=ArrayUtil.CombinedFieldArray(tag.getClass().getDeclaredFields(),f);
		}else{	
			try {
				Object c = (Object) Class.forName(tag.getClass().getSuperclass().getName()).newInstance();
				f=ArrayUtil.CombinedFieldArray(getAllFields( c),f,tag.getClass().getDeclaredFields());
			} catch (Exception e) {				
				e.printStackTrace();
			}
		}
		return f;
	}
	
	/**
	 * get all fields break for className
	 * @param tag
	 * @param className
	 * @return
	 */
	public static Field[] getAllFields(Object tag,Class<?> clazz){		
		Field [] f ={};
		if (tag.getClass().getSimpleName().equals(clazz.getSimpleName())) {
			f=ArrayUtil.CombinedFieldArray(tag.getClass().getDeclaredFields(),f);
		}else{	
			try {
				Object c = (Object) Class.forName(tag.getClass().getSuperclass().getName()).newInstance();
				f=ArrayUtil.CombinedFieldArray(getAllFields(c,clazz),f,tag.getClass().getDeclaredFields());
			} catch (Exception e) {				
				e.printStackTrace();
			}
		}
		return f;
	}
	
	public static String convertAllFeildToMD5(Object obj){
		StringBuffer sb = new StringBuffer();
		return sb.toString();
	}
	/**
	 *ConvertBeanToJsonObject
	 * @param target_obj  format object
	 * @return
	 */
	public static String convertBeanToJsonObject(Object target_obj)throws Exception{
		JSONObject j = null;
		Map<String, Object> map = BeanUtil.getAccessFields(target_obj);
		j = new JSONObject(map);
		return j.toString();
		
	}
	
	
	
		
	
	
}
